##### My (demuredemeanor) bashrc sub source prompt script
# Uses tabstop=4; shiftwidth=4 tabs; foldmarker={{{,}}};
# https://notabug.org/demure/dotfiles/
# legacy repo http://github.com/demure/dotfiles
# vim:set syntax=sh:

## This Changes The PS1
export PROMPT_COMMAND=__prompt_command      # Func to gen PS1 after CMDs

function __prompt_command() {
    local EXIT="$?"                         # This needs to be first
    PS1=""

    ### Colors to Vars ### {{{
    ## Inspired by http://wiki.archlinux.org/index.php/Color_Bash_Prompt#List_of_colors_for_prompt_and_Bash
    ## Terminal Control Escape Sequences: http://www.termsys.demon.co.uk/vtansi.htm
    ## Consider using some of: https://gist.github.com/bcap/5682077#file-terminal-control-sh
    ## Can unset with `unset -v {,B,U,I,BI,On_,On_I}{Bla,Red,Gre,Yel,Blu,Pur,Cya,Whi} RCol`
    local RCol='\[\e[0m\]'  # Text Reset

    # Regular                    Bold                          Underline                     High Intensity                BoldHigh Intensity             Background                High Intensity Backgrounds
    local Bla='\[\e[0;30m\]';    local BBla='\[\e[1;30m\]';    local UBla='\[\e[4;30m\]';    local IBla='\[\e[0;90m\]';    local BIBla='\[\e[1;90m\]';    local On_Bla='\e[40m';    local On_IBla='\[\e[0;100m\]';
    local Red='\[\e[0;31m\]';    local BRed='\[\e[1;31m\]';    local URed='\[\e[4;31m\]';    local IRed='\[\e[0;91m\]';    local BIRed='\[\e[1;91m\]';    local On_Red='\e[41m';    local On_IRed='\[\e[0;101m\]';
    local Gre='\[\e[0;32m\]';    local BGre='\[\e[1;32m\]';    local UGre='\[\e[4;32m\]';    local IGre='\[\e[0;92m\]';    local BIGre='\[\e[1;92m\]';    local On_Gre='\e[42m';    local On_IGre='\[\e[0;102m\]';
    local Yel='\[\e[0;33m\]';    local BYel='\[\e[1;33m\]';    local UYel='\[\e[4;33m\]';    local IYel='\[\e[0;93m\]';    local BIYel='\[\e[1;93m\]';    local On_Yel='\e[43m';    local On_IYel='\[\e[0;103m\]';
    local Blu='\[\e[0;34m\]';    local BBlu='\[\e[1;34m\]';    local UBlu='\[\e[4;34m\]';    local IBlu='\[\e[0;94m\]';    local BIBlu='\[\e[1;94m\]';    local On_Blu='\e[44m';    local On_IBlu='\[\e[0;104m\]';
    local Pur='\[\e[0;35m\]';    local BPur='\[\e[1;35m\]';    local UPur='\[\e[4;35m\]';    local IPur='\[\e[0;95m\]';    local BIPur='\[\e[1;95m\]';    local On_Pur='\e[45m';    local On_IPur='\[\e[0;105m\]';
    local Cya='\[\e[0;36m\]';    local BCya='\[\e[1;36m\]';    local UCya='\[\e[4;36m\]';    local ICya='\[\e[0;96m\]';    local BICya='\[\e[1;96m\]';    local On_Cya='\e[46m';    local On_ICya='\[\e[0;106m\]';
    local Whi='\[\e[0;37m\]';    local BWhi='\[\e[1;37m\]';    local UWhi='\[\e[4;37m\]';    local IWhi='\[\e[0;97m\]';    local BIWhi='\[\e[1;97m\]';    local On_Whi='\e[47m';    local On_IWhi='\[\e[0;107m\]';
    ### End Color Vars ### }}}

    if [ ${UID} -eq "0" ];then
        PS1+="${Red}\h \W ->${RCol} "       ## Set prompt for root
      else
        local PSCol=""                      ## Declare so null var fine
        local PSOpt=""                      ## Above, and fixes repeat issue

        if [ ${EXIT} != 0 ]; then
            ## can add `kill -l $?` to test to filter backgrounded
            PS1+="${Red}${EXIT}${RCol}"     ## Add exit code, if non 0
        fi

        ### Machine Test ### {{{
        local SHost="$(echo $HOSTNAME | awk 'match($0,/^[a-zA-Z0-9]+/) {print substr($0,RSTART,RLENGTH)}')"
        if [ ${HOSTNAME} == 'moving-computer-of-doom' ]; then
            local PSCol="$Cya"              ## For Main Computer
        elif [ ${HOSTNAME} == 'vps-of-doom' ]; then
            local PSCol="$Blu"              ## For VPS
            local PSOpt="${SHost} "
        elif [ ${HOSTNAME} == 'ma.sdf.org' ]; then
            local PSCol="${Yel}"            #@ For MetaArray
            local PSOpt="\h "
        elif [ ${HOSTNAME} == 'fencepost.gnu.org' ]; then
            local PSCol="${On_Pur}"         ## For Gnu
            local PSOpt="\h "
        elif [ ${HOSTTYPE} == 'arm' ]; then
            local PSCol="$Gre"              #@ For pi
            local PSOpt="${SHost} "
        elif [[ ${MACHTYPE} =~ arm-apple-darwin ]]; then
            local PSCol="$Gre"              ## For iOS
        elif [ ${MACHTYPE} == 'i486-pc-linux-gnu' ]; then
            local PSCol="$BBla"             ## For Netbook
            local PSOpt="${SHost} "
        elif [[ "${MACHTYPE}" == "x86_64--netbsd" && "${OSTYPE}" == "netbsd" ]]; then
            local PSCol="${Yel}"            ## For Main Cluster
            local PSOpt="\h "
        elif [ "${MACHTYPE}" == "mips-openwrt-linux-gnu" ]; then
            local PSCol="${On_Pur}"         ## For OpenWrt
            local PSOpt="\h "
          else
            local PSCol="${Pur}"            ## Un-designated catch-all
            local PSOpt="\h "
            MISSING_ITEMS+="machine-prompt, "
        fi
        ### End Machine Test ### }}}

        PS1+="${PSCol}${PSOpt}\W${RCol}"    ## Current working dir

        ### Check Jobs ### {{{
        type jobs &>/dev/null
        if [ $? == "0" ]; then
            ## Backgrounded running jobs
            local BKGJBS=$(jobs -r | wc -l | tr -d ' ')
            if [ ${BKGJBS} -gt 2 ]; then
                PS1+=" ${Red}[bg:${BKGJBS}]${RCol}"
            elif [ ${BKGJBS} -gt 0 ]; then
                PS1+=" ${Yel}[bg:${BKGJBS}]${RCol}"
            fi

            ## Stopped Jobs
            local STPJBS=$(jobs -s | wc -l | tr -d ' ')
            if [ ${STPJBS} -gt 2 ]; then
                PS1+=" ${Red}[stp:${STPJBS}]${RCol}"
            elif [ ${STPJBS} -gt 0 ]; then
                PS1+=" ${Yel}[stp:${STPJBS}]${RCol}"
            fi
        fi
        ### End Jobs ### }}}

        ### Add Git Status ### {{{
        ## Inspired by http://www.terminally-incoherent.com/blog/2013/01/14/whats-in-your-bash-prompt/
        if [[ $(command -v git) ]]; then
            local GStatus="$(git status --porcelain=2 -b 2>/dev/null | tr '\n' ':')"

            if [ -n "${GStatus}" ]; then
                ### Fetch Time Check ### {{{
                local LAST=$(stat -c %Y $(git rev-parse --git-dir 2>/dev/null)/FETCH_HEAD 2>/dev/null)
                if [ -n "${LAST}" ]; then
                    local TIME=$(echo $(date +"%s") - ${LAST} | bc)
                    ## Check if more than 60 minutes since last
                    if [ "${TIME}" -gt "3600" ]; then
                        git fetch 2>/dev/null
                        PS1+=' +'
                        ## Refresh var
                        local GStatus="$(git status --porcelain=2 -b 2>/dev/null | tr '\n' ':')"
                    fi
                fi
                ### End Fetch Check ### }}}

                ### Test For Changes ### {{{
                local GChanges="$(echo ${GStatus} | tr ':' '\n' | awk 'BEGIN {C=0} /^[12] .M/ {C++} END {print C}')"
                if [ "${GChanges}" == "0" ]; then
                    local GitColor=$Gre
                  else
                    local GitColor=$Red
                fi
                ### End Test Changes ### }}}

                ### Find Branch ### {{{
                local GBranch="$(echo ${GStatus} | awk 'match($0,/# branch.head [^ :]+/) {print substr($0,RSTART+14,RLENGTH-14)}')"
                if [ -n "${GBranch}" ]; then
                    GBranch="[${GBranch}]"              ## Add brackets for final output. Will now test against brackets as well.
                    if [ "${GBranch}" == "[master]" ]; then
                        local GBranch="[M]"             ## Because why waste space
                    fi
                    ## Test if in detached head state, and set output to first 8char of hash
                    if [ "${GBranch}" == "[(detached)]" ]; then
                        GBranch="($(echo ${GStatus} | awk 'match($0,/branch.oid [0-9a-fA-F]+/) {print substr($0,RSTART+11,RLENGTH-11)}' | cut -c1-8))"
                    fi
                  else
                    local GBranch="ERROR"               ## It could happen?
                fi
                ### End Branch ### }}}

                PS1+=" ${GitColor}${GBranch}${RCol}"    ## Add result to prompt

                ### Find Commit Status ### {{{
                ## Test Modified and Untracked for "0"
                # local GDel="$(echo ${GStat} | tr ':' '\n' | grep -c "^[ MARC]D")"

                ## Add 0 to knock off the '+'
                local GAhead="$(echo ${GStatus} | awk 'match($0,/# branch.ab \+[0-9]+ \-[0-9]+/) {split(substr($0,RSTART+12,RLENGTH-12),s," "); V=s[1]+0} END {if(V>0){print V}}')"
                if [ -n "${GAhead}" ]; then
                    PS1+="${Gre}↑${RCol}${GAhead}"      ## Ahead
                fi

                ## Needs a `git fetch`
                ## Multiply by -1 to remove the '-'
                local GBehind="$(echo ${GStatus} | awk 'match($0,/# branch.ab \+[0-9]+ \-[0-9]+/) {split(substr($0,RSTART+12,RLENGTH-12),s," "); V=s[2]*-1} END {if(V>0){print V}}')"
                if [ -n "${GBehind}" ]; then
                    PS1+="${Red}↓${RCol}${GBehind}"     ## Behind
                fi

                ## "[ MARC]" comes from https://git-scm.com/docs/git-status
                local GModified="$(echo ${GStatus} | tr ':' '\n' | awk 'BEGIN {C=0} /^[12] .M/ {C++} END {print C}')"
                if [ "${GModified}" -gt "0" ]; then
                    PS1+="${Pur}≠${RCol}${GModified}"   ## Modified
                fi

                local GUntracked="$(echo ${GStatus} | tr ':' '\n' | awk 'BEGIN {C=0} /^\?/ {C++} END {print C}')"
                if [ "${GUntracked}" -gt "0" ]; then
                    PS1+="${Yel}?${RCol}${GUntracked}"  ## Untracked
                fi
                ### End Commit Status ### }}}
            fi
          else
            MISSING_ITEMS+="git-prompt, "
        fi
        ### End Git Status ### }}}

        PS1+=" ${PSCol}-> ${RCol}"          ## End of PS1
    fi
}
